#pragma once
#include"Log.hpp"
#include <iostream>
#include"Thread.hpp"
#include"Task.hpp"
#include<queue>
#include<vector>
#include<pthread.h>
using namespace std;
using namespace ThreadModule;
const static int gdefaulttthreadnum=3;

template<typename T>
class ThreadPool
{
private:
    void LockQueue()
    {
        pthread_mutex_lock(&_mutex);
    }
    void UnlockQueue()
    {
        pthread_mutex_unlock(&_mutex);
    }
    void ThreadSleep()
    {
        pthread_cond_wait(&_cond,&_mutex);
    }
    void ThreadWakeup()
    {
        pthread_cond_signal(&_cond);
    }
    void ThreadWakeupAll()
    {
        pthread_cond_broadcast(&_cond);
    }
public:
    ThreadPool(int thread_num=gdefaulttthreadnum):_thread_num(thread_num),_wait_num(0),_isRuning(false)
    {
        pthread_mutex_init(&_mutex,nullptr);
        pthread_cond_init(&_cond,nullptr);
        LOG(INFO,"ThreadPool constructor thread_num:%d",_thread_num);
    }

    void HandleTask(const std::string &threadname)
    {
        LOG(INFO,"%s is running",threadname.c_str());
        while(true)
        {
            //1.保证队列安全
            LockQueue();
            //2.判断队列是否为空
            while(_queue_tasks.empty()&&_isRuning)
            {
                _wait_num++;
                //2.1 队列为空,等待
                ThreadSleep();
                _wait_num--;
            }
            //2.2 线程池已经退出，任务队列为空
            if(_queue_tasks.empty()&&!_isRuning){
                UnlockQueue();
                std::cout<<threadname<<" exit......"<<std::endl;
                break;
            }
            
            //3.一定有任务
            T t=_queue_tasks.front();
            _queue_tasks.pop();
            UnlockQueue();
            LOG(DEBUG,"%s get a task:%d done",threadname.c_str(),t);
            //4.处理任务,线程独占的任务
            t();
            LOG(DEBUG,"%s handler a task done,result :%s",threadname.c_str(),t.ResultToString().c_str());
        }
    }
    
    void InitThreadPool()
    {
        //创建线程,不启动
        for(int i=0;i<_thread_num;i++)
        {
            std::string name="thread_"+std::to_string(i+1);
            //_threads.emplace_back(Print, name);
            _threads.emplace_back(std::bind(&ThreadPool::HandleTask, this, std::placeholders::_1), name);
            LOG(INFO,"Init thread:%s done",name.c_str());
        }
        _isRuning=true;
    }

    void Start()
    {
        //启动线程
        for(auto &thread:_threads)
        {
            thread.Start();
            LOG(INFO,"Start thread:%s done",thread.name().c_str());
        }
        _isRuning=true;
    }

    void Wait()
    {
        //等待所有线程执行完毕
        for(auto &thread:_threads)
        {
            thread.Join();
            LOG(INFO,"Join thread:%s is quit...",thread.name().c_str());
        }
    }

    void Stop()
    {
        //1.保证队列安全
        LockQueue();
        //2.设置线程池状态为退出
        _isRuning=false;
        //3.唤醒所有等待的线程
        ThreadWakeupAll();
        UnlockQueue();
        LOG(INFO,"ThreadPool Stop done");
    }

    bool Enqueue(const T &t)
    {
        bool ret=false;
        //1.保证队列安全
        LockQueue();
        //2.添加任务
        if(_isRuning){
            _queue_tasks.push(t);
            //3.唤醒等待的线程
            if(_wait_num>0)
            {
                ThreadWakeup();
            }
            LOG(DEBUG,"Enqueue task success:%d done",t);
            ret=true;
        }
        UnlockQueue();
        return ret; 
    }

    ~ThreadPool()
    {
        pthread_mutex_destroy(&_mutex);
        pthread_cond_destroy(&_cond);
    }
private:
    int _thread_num;
    std::vector<Thread> _threads;
    std::queue<T> _queue_tasks;
    pthread_mutex_t _mutex;
    pthread_cond_t _cond;
    int _wait_num;
    bool _isRuning;
};
